package com.xhwl.centiotdata.suppliersystem.bailian;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.pojo.constant.BaiLianConstant;
import com.xhwl.centiotdata.pojo.dto.pedestrian.PedestrianIntegrationConfigDTO;
import com.xhwl.common.dto.cent.iotdata.bailian.BaiLianResponseBean;
import com.xhwl.common.dto.cent.iotdata.bailian.IDataSetter;
import com.xhwl.common.dto.cent.iotdata.bailian.PedestrianSyncDTO;
import com.xhwl.common.dto.cent.iotdata.bailian.PedestrianSyncTaskDTO;
import com.xhwl.common.pojo.cent.bi.PedestrianRecordCompanyHour;
import com.xhwl.common.pojo.cent.bi.PedestrianRecordProjectHour;
import com.xhwl.common.utils.CalendarUtil;
import com.xhwl.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author： lianghz
 * @Description：
 * @Date 2021/09/20/ 10:07
 */
@Service
public class PedestrianBaiLianHandler {
    private static final Logger log = LoggerFactory.getLogger(PedestrianBaiLianHandler.class);

    @Autowired
    private GeneralBaiLianHandler generalBaiLianHandler;

    /**
     * 历史接口，数据中只有游逛时长有效
     *
     * @return
     */
    private String getHistoryUrl() {
        return BaiLianConstant.CUSTOMER_FLOW_HISTORY_URL;
    }

    /**
     * 查询客流接口，所有客流数据以这个接口为准，包括历史数据
     *
     * @return
     */
    private String getTodayUrl() {
        return BaiLianConstant.CUSTOMER_FLOW_TODAY_URL;
    }

    /**
     * @param configDTO
     * @param intervalDays 提前多少天，null的话是当日
     * @return
     */
    public JSONObject pullTodayRecord(PedestrianIntegrationConfigDTO configDTO, Integer intervalDays) {
        return request(configDTO.getIpAndPort() + getTodayUrl(), getParams(intervalDays));
    }

    /**
     * @param configDTO
     * @param date      传null或者空串，代表查询日期是当日
     * @return
     */
    public JSONObject pullTodayRecord(PedestrianIntegrationConfigDTO configDTO, String date) {
        if (configDTO.isMockMode()) {
            return BaiLianMockUtil.mockPedestrianTodayData(date);
        }
        return request(configDTO.getIpAndPort() + getTodayUrl(), getParams(date));
    }

    /**
     * @param configDTO
     * @param date      日期，格式 yyyy-MM-dd
     * @return
     */
    public JSONObject pullHistoryRecord(PedestrianIntegrationConfigDTO configDTO, String date) {
        if (configDTO.isMockMode()) {
            return BaiLianMockUtil.mockPedestrianHistoryData(date);
        }
        return request(configDTO.getIpAndPort() + getHistoryUrl(), getParams(date));
    }

    /**
     * @param configDTO
     * @param intervalDays 提前多少天，null的话是当日
     * @return
     */
    public JSONObject pullHistoryRecord(PedestrianIntegrationConfigDTO configDTO, Integer intervalDays) {
        return request(configDTO.getIpAndPort() + getHistoryUrl(), getParams(intervalDays));
    }


    private JSONObject request(String url, HashMap<String, Object> params) {
        JSONObject resultObject = generalBaiLianHandler.post(url, params);
        String data = resultObject.getString("data");
        if (StringUtils.isEmpty(data)) {
            log.error("post path:{};params:{}; data is null !", url, JSON.toJSONString(params));
            return null;
        }
        return JSON.parseObject(data);
    }

    /**
     * @param date yyyy-MM-dd
     * @return
     */
    private HashMap<String, Object> getParams(String date) {
        HashMap<String, Object> params = new HashMap<>(2);
        params.put("date", date);
        params.put("departmentID", null);
        return params;
    }

    private HashMap<String, Object> getParams(Integer intervalDays) {
        String date = null;
        Date preDate = getPreDate(intervalDays);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (preDate != null) {
            date = sdf.format(preDate);
        }
        return getParams(date);
    }

    /**
     * 获取提前某一天的date
     *
     * @return
     */
    public Date getPreDate(Integer intervalDays) {
        if (intervalDays == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, intervalDays);
        return calendar.getTime();
    }

    private String getPattern() {
        return CalendarUtil.DATE_FORMAT[1];
    }

    /**
     * 获取某一天的记录
     *
     * @param date yyyy-MM-dd
     * @return
     */
    public PedestrianSyncTaskDTO getSyncRecord(PedestrianIntegrationConfigDTO configDTO, String date) {
        PedestrianSyncTaskDTO taskDTO = new PedestrianSyncTaskDTO();
        taskDTO.setSuccess(false);
        if (!CalendarUtil.isAccurateDate(date, getPattern())) {
            taskDTO.setErrorMsg("错误的时间传参," + date);
            return taskDTO;
        }
        JSONObject todayRecord, historyRecord;
        try {
            todayRecord = pullTodayRecord(configDTO, date);
            String todayDate = CalendarUtil.getDateStr(getPattern(), new Date());
            //如果是当天，还没有游逛时长数据，不需要history请求
            historyRecord = todayDate.equals(date) ? null : pullHistoryRecord(configDTO, date);
        } catch (Exception e) {
            log.error("请求百联异常", e);
            taskDTO.setErrorMsg("请求百联异常");
            return taskDTO;
        }
        PedestrianSyncDTO pedestrianSyncDTO = transformResult(configDTO, todayRecord, historyRecord);
        taskDTO.setPedestrianSyncDTO(pedestrianSyncDTO);
        taskDTO.setSuccess(true);
        return taskDTO;
    }

    public PedestrianSyncDTO transformResult(PedestrianIntegrationConfigDTO configDTO, JSONObject todayRecord, JSONObject historyRecord) {
        BaiLianResponseBean today = todayRecord.toJavaObject(BaiLianResponseBean.class);
        BaiLianResponseBean history = historyRecord.toJavaObject(BaiLianResponseBean.class);
        //从history中填充游逛时长
        fillWanderTime(today, history);
        List<PedestrianRecordProjectHour> storeHours = today.getStoreFlow().stream().map(storeFlowObject -> {
            PedestrianRecordProjectHour pedestrianRecordProjectHour = new PedestrianRecordProjectHour();
            setFlowDate(configDTO.getProjectId(), pedestrianRecordProjectHour, storeFlowObject);
            return pedestrianRecordProjectHour;
        }).collect(Collectors.toList());

        List<PedestrianRecordCompanyHour> companyHours = today.getDepartmentFlow().stream().map(departmentFlowObject -> {
            PedestrianRecordCompanyHour companyHour = new PedestrianRecordCompanyHour();
            companyHour.setCompanyCode(departmentFlowObject.getDepartmentID());
            setFlowDate(configDTO.getProjectId(), companyHour, departmentFlowObject);
            return companyHour;
        }).collect(Collectors.toList());
        PedestrianSyncDTO pedestrianSyncDTO = new PedestrianSyncDTO(storeHours, companyHours);
        return pedestrianSyncDTO;
    }

    private void setFlowDate(Integer projectId, IDataSetter iDataSetter, BaiLianResponseBean.IFlow iFlow) {
        iDataSetter.setProjectId(projectId);
        iDataSetter.setWanderTime(iFlow.getWanderTime());
        try {
            iDataSetter.setIngestionTime(CalendarUtil.getDate(CalendarUtil.DATE_FORMAT[0], iFlow.getTime()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        iDataSetter.setInFlow(iFlow.getPedestrianInFlow());
        iDataSetter.setOutFlow(iFlow.getPedestrianOutFlow());
        iDataSetter.setTotalFlow(iFlow.getPedestrianInFlow() + iFlow.getPedestrianOutFlow());
    }

    private void fillWanderTime(BaiLianResponseBean today, BaiLianResponseBean history) {
        if (today == null || history == null)
            return;
        history.getStoreFlow().stream().forEach(storeFlowObject ->
                setStoreWanderTime(today.getStoreFlow(), storeFlowObject.getWanderTime()));
        history.getDepartmentFlow().stream().forEach(departmentFlowObject ->
                setDepartmentWanderTime(today.getDepartmentFlow(), departmentFlowObject.getWanderTime(), departmentFlowObject.getDepartmentID()));
    }

    /**
     * 每天的wanderTime更新到当天的 12:00:00数据上
     */
    private static final String UPDATE_TARGET_CLOCK = " 12:00:00";

    /**
     * 设置给12点 todayStoreFlow
     *
     * @param storeFlow
     * @param wanderTime
     */
    private void setStoreWanderTime(List<BaiLianResponseBean.StoreFlowObject> storeFlow, Double wanderTime) {
        BaiLianResponseBean.StoreFlowObject storeFlowObject1 = storeFlow.stream().filter(storeFlowObject -> storeFlowObject.getTime().endsWith(UPDATE_TARGET_CLOCK))
                .findAny().orElse(null);
        if (storeFlowObject1 != null) {
            storeFlowObject1.setWanderTime(wanderTime);
        }
    }

    /**
     * 给相同店铺id的设置一个wanderTime，设置给第一个找到的time
     *
     * @param departmentFlow
     * @param wanderTime
     * @param departmentId
     */
    private void setDepartmentWanderTime(List<BaiLianResponseBean.DepartmentFlowObject> departmentFlow, Double wanderTime, String departmentId) {
        BaiLianResponseBean.DepartmentFlowObject departmentFlowObject1 = departmentFlow.stream().filter(departmentFlowObject ->
                StringUtils.equals(departmentFlowObject.getDepartmentID(), departmentId) && departmentFlowObject.getTime().endsWith(UPDATE_TARGET_CLOCK))
                .findAny().orElse(null);
        if (departmentFlowObject1 != null) {
            departmentFlowObject1.setWanderTime(wanderTime);
        }
    }

}
